/*
 * lex.c
 *
 *  Created on: 2009-5-12
 *      Author: hwg
 */

#include"../header/common.h"

void match(LinkList word , LinkList key)
{
	int i = 1;
	int j = 1;
	ElemType words;
	ElemType keys;
	lex session;
	while(Listgetnode(word , i , &words) != error)
	{
		j = 1;
		while(Listgetnode(key , j , &keys)!= error)
		{
			initles(&session , keys.unikeynode.words , words.uniwordnode.words);
			if(lex_make(&session) == ok)
			{
				strcpy(words.uniwordnode.exp ,keys.unikeynode.exp);
				Listsetnode(word , i , &words);
				printf("\nthe words = %s accp by = %s the ext is %s\n", words.uniwordnode.words,keys.unikeynode.words, keys.unikeynode.exp);
				break;
			}
			else
			{
				j = j + 1;
				continue;
			}
		}
		i = i + 1;
	}
}

void initles(lex *session, char * keys, char* words)
{
	session->nextkeynode.top = 0;
	session->keys.top = 0;
	session->serror.top = 0;
	session->state.top = 0;
	session->words.top = 0;
	session->wordscallback.top = 0;
	session->mode.top = 0;
	session->su = ok;
	cinitia(&(session->keys), keys);
	cinitia(&(session->words), words);
	cpush(&(session->serror),'n');

}

int lex_make(lex *session)
{
	char operate;
	char key;
	int next;
	int mode;
	while(!isend(session))
	{
		key = cpop(&(session->keys));
		if(key == '(')
		{
			operate = getotheropration(&(session->keys),&next);
			if(operate == '*')
			{
				inpush(&(session->mode),ad);
				inpush(&(session->nextkeynode),next);
				inpush(&(session->state),session->keys.top + 1);//返回到（
				inpush(&(session->wordscallback),session->words.top);
				//"\n\t%d\t%d\n",session->words.top,ingettop(&(session->wordscallback)));
				cpush(&(session->serror),'y');
				int m = lex_make(session);
				if (m == error)
					return error;
				else
					continue;

			}
			else if(operate == '&')
			{
				inpush(&(session->mode),one);
				inpush(&(session->wordscallback),session->words.top);
				inpush(&(session->nextkeynode),next);
				cpush(&(session->serror),'n');
				int m = lex_make(session);
				if (m == error)
					return error;
				else
					continue;
			}
			else
			{
			if(operate == '/')
				{
					inpush(&(session->mode),orr);
					inpush(&(session->wordscallback),session->words.top);
					inpush(&(session->nextkeynode),next);
					cpush(&(session->serror),'y');
					int m = lex_make(session);
					if (m == error)
						return error;
					else
								//session->keys.top = inpop(&(session->nextkeynode));
						continue;
				}
				else
				{
					inpush(&(session->mode),nu);
					inpush(&(session->wordscallback),session->words.top);
					inpush(&(session->nextkeynode),next);
					cpush(&(session->serror),'y');
					int m = lex_make(session);
					if (m == error)
						return error;
					else
						continue;
				}
			}
		}
		else if(key==')')
		{
			operate  = cgettop(&(session->keys));
			if(operate == '*')
			{


				if (session->su == ok)
				{
					cpop(&(session->serror));
					mode = inpop(&(session->mode));
					inpop(&(session->mode));
					inpop(&(session->nextkeynode));
					inpop(&(session->wordscallback));
					session->keys.top = inpop(&(session->state));
					session->su = ok;
				}

				else
				{
					cpop(&(session->serror));
					mode = inpop(&(session->mode));
					inpop(&(session->mode));
					inpop(&(session->wordscallback));
					/*新增*/
					session->keys.top = inpop(&(session->nextkeynode));
//

					session->su  = error;
				}
				return complete;
			}
			else if(operate == '/')
			{
				cpop(&(session->serror));
				mode = inpop(&(session->mode));
				inpop(&(session->wordscallback));


				if (session->su == ok)
				{
					session->su = ok;
					inpop(&(session->nextkeynode));
					session->keys.top = inpop(&(session->nextkeynode));
				}
				else
				{
					session->su  = ok;
					session->keys.top = inpop(&(session->nextkeynode));
				}
				return complete;
			}
			else if(operate == '&')
			{
				cpop(&(session->serror));
				mode = inpop(&(session->mode));
				inpop(&(session->wordscallback));
				session->keys.top = inpop(&(session->nextkeynode));
				if (session->su == ok)
				{
					return complete;
				}
				else
				{
					return error;
				}

			}
			else
			{
				cpop(&(session->serror));
				mode = inpop(&(session->mode));
				inpop(&(session->wordscallback));
				session->keys.top = inpop(&(session->nextkeynode));
				return complete;
			}
		}
		else
		{
			printf("\nthe key:\t%c?==\t%c(words)",key,cgettop(&(session->words)));
			if(key == cpop(&(session->words)))
			{
				session->su  = ok;
				printf("\tYes key next and words next!");
				continue;
			}
			else
			{	printf("\tNo key back and words back!");
				if(cgettop(&(session->serror)) == 'y')
				{
					mode = inpop(&(session->mode));
					if(mode == orr)
					{
						session->words.top = inpop(&(session->wordscallback));
						session->keys.top = inpop(&(session->nextkeynode));
						cpop(&(session->serror));
						session->su  = error;
						return	ncomp;

					}
					else if(mode == ad)
					{
						session->words.top = inpop(&(session->wordscallback));
						session->keys.top = inpop(&(session->nextkeynode));
						cpop(&(session->serror));
						inpop(&(session->state));
						session->su  = error;
						return ncomp;
					}
					else if (mode == one)
					{
						//cpush(&(session->serror),'y');
						cpop(&(session->serror));
						session->words.top = inpop(&(session->wordscallback));
						session->keys.top = inpop(&(session->nextkeynode));
						session->su  = error;
						return ncomp;

					}
					else
					{
						//cpush(&(session->serror),'y');
						cpop(&(session->serror));
						session->words.top = inpop(&(session->wordscallback));
						session->keys.top = inpop(&(session->nextkeynode));
						session->su  = error;
						return ncomp;
					}

				}
				else
				{
					session->words.top = inpop(&(session->wordscallback));
					putchar('E');
					return error;
				}
			}
		}

	}

	putchar(cgettop(&(session->keys)));
	putchar(cgettop(&(session->words)));
	if((cgettop(&(session->words)) == ';'))
		return ok;
	else
		return error;
}
int isend(lex *session)
{
	if((cgettop(&(session->keys)) == ';'))
	{
		return 1;
	}

	else
		return 0;
}
char getotheropration(cstack *s, int *next)
{
	int p = s->top;
	int zcount = 0;
	int fcount = 0;
	char o = '@';
		while( o != ';')
		{
			o = cpop(s);
			//putchar(o);
					if(o == '(')
						zcount = zcount + 1;
					else if(o == ')')
					{
						fcount = fcount + 1;
						if(fcount == zcount + 1)
							{
								o = cpop(s);
								if(o == '*'|| o == '/'|| o == '&')
									*next = s->top;
								else
									*next = s->top + 1;
								s->top = p;
								return o;
							}
						else
							continue;
					}
					else
						continue;
		}
	return '#';
}

